#include "BlackBear.h"

#include <QListIterator>
#include <QVector>

#include "Bear.h"
#include "BBObject.h"
#include "SqlManager.h"
#include "BearFactory.h"
#include "XmlParser.h"
#include "BBTable.h"

int ATTRIBUTE_ID_PARENT_DEFAULT = -1;

BlackBear::BlackBear()
{
	//DOES NOTHING
}

BlackBear::BlackBear( QSqlDatabase* dataBase, QString& connectionName )
{
	m_dataBase = dataBase;
	m_connectionName = connectionName;
	m_factory = BearFactory::instance();
}

BlackBear::~BlackBear()
{
	//Close the current connection
	m_dataBase->removeDatabase( m_connectionName );

	//Check if this is the last connection
	if( m_dataBase->connectionNames().size() == 0 )
	{
		//Close database
		m_dataBase->close();
	}
}

bool BlackBear::save( Bear& bear )
{
	int parentId = ATTRIBUTE_ID_PARENT_DEFAULT;
	SqlManager* sqlManager = SqlManager::instance();
	QListIterator<BBObject*> iteratorObjectsOrder( bear.getObjectsInitializationOrder() );
	BBObject* currentObject;
	bool ret = true;

	//Get all objects, set their parent id with the last object's id and save in base 
	//Bear organizes its objects from superclass to subclasses
	while ( iteratorObjectsOrder.hasNext() )
	{
		currentObject = iteratorObjectsOrder.next();
		
		//Check if current object is new or exists in database
		if ( currentObject->id() == BBObject::ATTRIBUTE_ID_VALUE_DEFAULT )
		{	
			currentObject->setParentId( parentId );
			
			//Check if object was inserted
			if( !sqlManager->insertRow( *this, *currentObject ) )
			{
				ret = false;
				break;
			}

			//Get id to set the next object's id father
			parentId = currentObject->id();
		}
		//Object has id, so it exists
		else
		{
			//Check if object was updated
			if( !sqlManager->updateRow( *this, *currentObject ) )
			{
				ret = false;
				break;
			}
		}
	}

	//Check if object was saved
	if ( ret )
	{
		//Indicate that object was saved
		bear.setHasEdited( false );
	}
	
	return ret;
}

int BlackBear::saveComposite( Bear& bear )
{
	save( bear );

	return bear.getFirstObject()->id();
}

bool BlackBear::deleteObject( Bear& bear )
{
	SqlManager* sqlManager = SqlManager::instance();
	QListIterator<BBObject*> iteratorObjectsOrder( bear.getObjectsInitializationOrder() );
	BBObject* currentObject;
	bool ret = true;

	//Get all objects
	while ( iteratorObjectsOrder.hasNext() )
	{
		currentObject = iteratorObjectsOrder.next();

		//Check if object was saved before
		if ( currentObject->id() != BBObject::ATTRIBUTE_ID_VALUE_DEFAULT )
		{
			ret = sqlManager->deleteRow( *this, *currentObject );
		}
		else
		{
			//TODO Error message: Objeto nao esta presente na base de dados (id = -1)
			ret = false;
		}
	}	

	return ret;
}

Bear* BlackBear::load( QString className, int objectId )
{
	SqlManager* sqlManager = SqlManager::instance();
	QVector<int> bearsIds = sqlManager->getIds( *this, className );
	bool existObject = true;
	Bear* bear;

	// Check if id passed exist in database
	if ( bearsIds.contains( objectId ) )
	{
		bear = m_factory->createBear( className );
		QListIterator<BBObject*> iteratorObjectsOrderReversed( bear->getObjectsInitializationOrderReversed() );
		BBObject* currentObject;

		//Set first object with the id passed from user
		if( iteratorObjectsOrderReversed.hasNext() )
		{
			currentObject = iteratorObjectsOrderReversed.next();
			currentObject->setId( objectId );

			//Check if manager took the object
			if( !sqlManager->selectRow( *this, *currentObject ) )
			{
				existObject = false;
			}
		}

		//Get the parent's id of the object. This parent's id will be the id for the next object 
		int parentId = currentObject->getParentId();

		//Set all objects, less the first
		while ( iteratorObjectsOrderReversed.hasNext() )
		{
			currentObject = iteratorObjectsOrderReversed.next();
			currentObject->setId( parentId );

			//Check if manager took the object
			if( !sqlManager->selectRow( *this, *currentObject ) )
			{
				existObject = false;
				break;
			}

			parentId = currentObject->getParentId();
		}
	}
	else
	{
		existObject = false;
	}

	//Check if object exist
	if ( !existObject )
	{
		bear = NULL;
	}

	return bear;
}

std::vector<Bear*> BlackBear::load( QString className )
{
	SqlManager* sqlManager = SqlManager::instance();
	QVector<int> bearsIds = sqlManager->getIds( *this, className );
	QVector<Bear*> bears( bearsIds.count() );

	//Get all bears with respective id
	for ( int i = 0; i < bearsIds.count(); i++ )
	{
		bears[i] = load( className, bearsIds[i] );
	}
	
	return bears.toStdVector();
}

bool BlackBear::createTables( QString& xmlMappingFileClass )
{
	bool ret = true;
	XmlParser* parser = XmlParser::instance();
	SqlManager* manager = SqlManager::instance();
	QListIterator<BBTable> i( *parser->getTables( xmlMappingFileClass ) );

	//Get all tables
	while ( i.hasNext() && ret )
	{
		BBTable currentTable = i.next();

		ret = manager->createTable( *this, currentTable );
	}

	return ret;
}
